package com.shjzit.loglib.net_http;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.shjzit.loglib.bean.BaseResp;
import com.shjzit.loglib.db.entity.LogEntity;
import com.shjzit.loglib.utils.PrintLog;
import com.shjzit.loglib.utils.SSLSocketClient;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

/**
 * User:zhouxc
 * Date:2022/9/8
 * Time:13:44
 */
public class OkhttpRequestManager {
    private final int CACHE_SIZE = 10 * 1024 * 1024; // 10 MiB
    private final String CACHE_FILE_NAME = "JZIT_LOG";
    private OkHttpClient client;
    private Context mContext;
    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    public static Handler mHandler = new Handler();
    private Gson gson = new Gson();

    public static Handler getHandler() {
        if (mHandler == null) {
            mHandler = new Handler();
        }
        return mHandler;
    }

    private volatile static OkhttpRequestManager instance = null;

    private OkhttpRequestManager() {
    }


    public static OkhttpRequestManager getInstance() {
        if (null == instance) {
            synchronized (OkhttpRequestManager.class) {
                if (null == instance) {
                    instance = new OkhttpRequestManager();
                }
            }
        }
        return instance;
    }


    /**
     * 初始化,上下文和 okhttpclient 对象
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context.getApplicationContext();
        client = getClient();
    }

    private OkHttpClient getClient() {
        if (client == null) {
            OkHttpClient.Builder mBuilder = new OkHttpClient.Builder().
                    connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(), new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }
                    })
                    .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
                    .cache(new Cache(mContext.getExternalFilesDir(CACHE_FILE_NAME), CACHE_SIZE));
            client = mBuilder.build();
        }
        return client;
    }

    /**
     * 发送网络请求,开始上传数据,客户端调用
     *
     * @param
     * @param url
     * @param entity
     */
    public String doPost(String url, String content, Map<String, String> headers, LogEntity entity) throws Exception {
        return httpPost(url, content, headers, entity);
    }


    private String httpPost(String url, String content, Map<String, String> headers, LogEntity entity) throws Exception {
        PrintLog.print_i("开始上传 --> logId : " + entity.getLogId());
        Request.Builder requestBuilder = new Request.Builder().url(url);
        requestBuilder.post(RequestBody.create(MEDIA_TYPE_JSON, content));
        requestBuilder = configHeaders(requestBuilder, headers);
        Request build = requestBuilder.build();
        ResponseBody body = getClient().newCall(build).execute().body();
        if (body != null) {
            return body.string();
        }
        return null;
    }

    private FormBody.Builder configPostParam(FormBody.Builder builder, Map<String, String> paramsMap) {
        if (paramsMap != null) {
            Set<Map.Entry<String, String>> entries = paramsMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                builder.add(key, value);
            }
        }
        return builder;
    }

    private Request.Builder configHeaders(Request.Builder builder, Map<String, String> headers) {
        if (headers == null || headers.size() == 0) {
            return builder;
        }
        Set<Map.Entry<String, String>> entries = headers.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            builder.addHeader(key, value);
        }
        return builder;

    }


    private void handleResult(ResponseBody response, IResponseCallback callback, LogEntity entity) throws Exception {
        final String result = response.string();
        if (TextUtils.isEmpty(result)) {
            PrintLog.print_e("Okhttp Response is null  insertLogs  error");
            client.dispatcher().cancelAll();
            client = null;
            return;
        }
        BaseResp resp = gson.fromJson(result, BaseResp.class);
        if (callback != null && resp != null && "200".equals(resp.getResultCode())) {
            PrintLog.print_i("Okhttp 上传成功!!");
            getHandler().post(() -> callback.onResponse(result, entity));
        } else {
            PrintLog.print_e("Okhttp 上报失败  " + resp.getResultCode() + " " + resp.getResultMsg());
        }
    }

    private void handleError(Exception e, final IResponseCallback callback) {
        PrintLog.print_e("Okhttp Error " + e.getMessage());
        if (callback != null) {
            getHandler().post(() -> callback.onFail(e.getMessage()));
        }
    }

    public void cancel(String tag) {
        if (client != null) {
            for (Call call : client.dispatcher().queuedCalls()) {
                if (call.request().tag().equals(tag)) {
                    call.cancel();
                }
            }
        }
    }
}
